home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
176-200
/
191
/
blk
/
blk.doc
< prev
next >
Wrap
Text File
|
1995-03-13
|
11KB
|
311 lines
blk - Automatic Requester Generator
Stuart Ferguson
Blk generates C code for declaring requesters. It automatically formats
borders and text and generates the declarations for them. The requester
can contain boolean, string and proportional gadgets.
Boxes:
A Requester and all its internal structures are described to blk as a
tree of nested boxes. The root box is the Requester itself. Inner
boxes can be stacked horizontally or vertically or be within each
other. Borders and text strings are also boxes for the purpose of
formatting. The box grammer, which is loosly based on lisp syntax, can
be described by the BNF-like description given below. (Non-terminal
symbols are named and terminal symbols are double quoted strings.)
box :== fill | text | bord | block | seq
fill :== "f"
text :== "(t" onum str ")"
str :== [double quoted string]
bord :== rule | "(" rule num onum ")"
rule :== "|" | "-"
block :== "(b" num num ")"
seq :== "(" ("h"|"v") blist ")"
blist :== box | box blist
onum :== num | [nothing]
num :== [unsigned integer]
Some examples:
The following box description would produce a 10 x 10 pixel area with
borders on all four sides:
(h | (v - (b 10 10) - ) | )
The central structure, "(b 10 10)," is a 10 x 10 block. This is one of
three boxes in a vbox, or vertically oriented list of boxes. The other
two boxes in the list are hrules, the "-"'s, which are horizontal "rules,"
or lines. This produces a box containing an empty area with lines above
and below it. This box is further included with two vertical rules, "|,"
in an hbox - a horizontally oriented list. This puts horizontal lines
on each side of the box, closing the square.
----- |-----|
xxxxx |xxxxx|
xxxxx |xxxxx|
xxxxx |xxxxx|
----- |-----|
Rules are elastic, and while they have no intrinsic length of their own,
they will expand to fill any space available within their bounding box.
The vbox above:
(v - (b 10 10) - )
has dimensions 10 x 12, so each horizontal rule expands to a length of
10 to fill the enclosing box.
Fills are another type of elastic object. For example, suppose you wanted
to format a set of strings, like:
Line #1
Blah Blah
ETC
You could list the text boxes in a vbox, thus:
(v (t "Line #1") (t "Blah Blah") (t "ETC"))
This would produce the formated lines as above. But then suppose you wanted
each line centered within its box. For this you use fills. Each fill
expands to take up as much free space as it can within its bounding box,
and if a string is sandwiched between two fills horizontally, it will be
squeezed by competing fills into the center of its bounding box.
(v
(h f (t "Line #1") f)
(h f (t "Blah Blah") f)
(h f (t "ETC") f)
)
Now the boxes within the outer vbox are not text boxes but hboxes
containing text boxes and fills to the left and right. The width of the
vbox is computed as the maximum width of each box it contains. Since
fills have no intrinsic size, the widest hbox is the one containing the
text box (t"Blah Blah"), which has a width of 9 characters (blk always
assumes a fixed size font). If the characters are 8 pixels wide, the
largest hbox will be 72 pixels. Each of the other two shorter hboxes
are contained within a vbox also of width 72, so each fill expands to
make up the difference. For example, the first hbox contains two fills
and a 56 pixel wide text box. To fill up a 72 pixel wide bounding box,
each fill can expand 8 pixels horizontally, thus centering the text box
inbetween them. The result is:
Line #1
Blah Blah
ETC
This whole structure is just a box, and can be used within other box
structures. For example, to put a border around the above box, you could
use the definition from the first example. Specifically:
(h | (v -
(v
(h f (t"Line #1") f)
(h f (t"Blah Blah") f)
(h f (t"ETC") f)
)
-) |)
The problem with this (you will see if you try it) is that the rules
suround the text too closely. Since there is no space between the text and
the lines they lie almost right on top of each other. Text boxes look fine
right next to each other, but rules need to be explicitly spaced away from
text. This can be done with "struts," blocks used explicitly as spacers,
like so:
(h | (v - (b 0 5) (h (b 5 0)
(v
(h f (t"Line #1") f)
(h f (t"Blah Blah") f)
(h f (t"ETC") f)
)
(b 5 0)) (b 0 5) -) |)
The 0 x 5 and 5 x 0 blocks have no volume but since they have width or
height, they affect the spacing of the other components in their h- or
vboxes.
Text and rules take on the default color (see "blk files" below) unless the
color is explicitly stated. For text boxes this is done with the optional
parameter in the text box description, as in (t 3 "hi there"), which
specifies that the text be color #3. For rules, a different description
format is used. Instead of simply | or -, a form such as (| 1 3) or (- 1 2)
is used. The two examples create a vrule of color 3 and an hrule of color 2
respectively. The first number is the width of the rule and should always
be 1.
With these simple tools, it is possible to design a wide variety of nicely
layed-out requesters without dealing with a single coordinate or C struct.
What is more, the strings in the above box definition could be changed to
anything, and the result would still be three strings centered within a
perfectly sized box.
Blk also supports a 'C'-style preprocesser for include files, macros,
comments and "ifdef's". Macros can make deeply nested box structures
more readable and consistent.
Gadgets:
Any sub-box in a box definition can be defined to be a gadget hit box by
following it with the sequence:
":" num
From the above example, each text box could be defined as a hit box for a
gadget by restating it as:
(h f (t"Line #1"):1 f)
(h f (t"Blah Blah"):2 f)
(h f (t"ETC"):3 f)
Given these box definitions, blk will generate code for 3 BOOLEAN,
RELVERIFY, REQGADGET, GADGHCOMP gadgets with the GadgetID's 1,2 and 3.
Other types of gadgets can be defined using an extended gadget definition.
These are of the form:
num {"s"|"p"|"pv"|"ph"} {":"id} flags
Stuff in {}'s is optional; "id" and "flags" are double-quoted strings.
"Num" is the id number for the gadget given after the ":" in the box
definition. The optional "s", "p", "pv" and "ph" specify string or
proportional gadgets, the default being boolean. "ph" is a FREEHORIZ
proportional gadget, "pv" is FREEVERT, and "p" is both. The optional
"id" string specifies a string to be used for the GadgetID field in the
gadget struct instead of just using "0x<num>," where num is the id
given in the box description. "Flags" is a set of characters used to
specify flags available in defining a gadget. Valid flags are (case
is significant):
B : GADGHBOX
t : TOGGLESELECT
v : RELVERIFY
e : ENDGADGET
i : GADGIMMEDIATE
c : STRINGCENTER (string gadgets only)
f : FOLLOWMOUSE
Some examples:
1ph"" - horizontally moving proportional gadget with no flags
7:"OK_ID""ev" - boolean gadget with id "OK_ID"
RELVERIFY and ENDGADGET flags set
5s"v" - RELVERIFY string gadget
5s:"STR_ID""i" - string gadget with id "STR_ID", GADGIMMEDIATE flag
Blk output:
The code that blk outputs follows some simple conventions. These were
implemented for my own convenience and can be changed by altering the source
code. Structs are assigned in arrays, the name of each array being some
base name followed by the type of struct. For example, if the base name
were "xyz," some structs would be "xyz_req," "xyz_str," etc. They are:
struct Requester <base>_req /* not an array */
struct Gadget <base>_gad[]
struct IntuiText <base>_txt[]
struct Border <base>_brd[]
short <base>_brd_XY[]
UBYTE <base>_nbuf[][NUMCHR]
struct StringInfo <base>_sinfo[]
struct Image <base>_pimg[]
struct PropInfo <base>_pinfo[]
Some of these may be ommited if there are no data of that type.
In user code, the symbol "ta" must be declared as struct TextAttr as in:
struct TextAttr ta = { ... };
or
extern struct TextAttr ta;
To use string gadgets, the symbol "NUMCHR" must be #define'd as the number
of characters in the string buffer. The symbol "undo" must be declared as
UBYTE undo[NUMCHR];
to be used as the undo buffer for string gadgets (or #define'd as NULL).
The string buffers will be assigned in the order that they are encountered
in reading the box description, so the buffer for the first encountered
will be <base>_nbuf[0], the buffer for the second will be <base>_nbuf[1],
and so on.
Blk files:
A blk input file contains all the information to describe a single
requester. It starts with a string that is to be the base name for this set
of declarations. There are then two optional numbers which are the default
border color and default text color. Neither need to be specified and will
both default to 1. Then comes the box definition followed by a set of
extended gadget descriptions. Some examples are included in this release.
Using blk:
The blk commandline is:
blk [-p|q|v|s|d|g] <infile> [<outfile>]
<infile> - Input description file -- required.
<outfile> - Output 'C' header file.
-p - Print box description.
-s - Output 'C' header file to stdout.
-d - Display a preview Requester.
-g - Write global declarations.
-q - Run quiet.
-v - Run verbose.
"Infile" is the input requester description. If no output is specified,
the resulting Requester will be displayed in a window. If output is
specified, blk will not normally display a preview, but it will if the
"-d" option is specified. The "-p" option prints a description of the
formatted box tree structure to stdout. This can be a huge ammout of
output, but can be useful if you need to know the exact coordinates or
size of something. "-g" will write the 'C' declrations as global; the
default is "static". 'C' output can be redirected to stdout with the
"-s" option. If this option is used, "-q" is also assumed.
The preview Requester will work and can be played with. Blk will display
the classes of the messages it gets from Intuition as you play with the
Gadgets in the Requester. If the Requester itself has no "ENDGADGET"
type gadgets for terminating the Requester, blk allows you to end the
preview session by pressing ESC when the preview window is active.
Caveats:
The program is massivly recursive. Be sure that you have enough stack
to deal with the box description you give. The deeper you nest your
box descriptions, the deeper blk will go in interpreting them. I keep
my stack at 12000 and don't have any problems with it.
Blk is intended in the same spirit as a compiler, so the 'C' output
declarations are not designed to be directly editable. For example,
the Gadget flags are not described symbolically, but rather are dumped
numerically into the declared structures. The answer to problems
with this is to modify the blk source.
If you do decide to hack the source, be so kind as to keep me informed
of any useful improvements you make in case I decide to do yet another
version.
Stuart Ferguson 1/89
(shf@well.UUCP)
123 James Ave.
Redwood City, Ca.
94062